﻿using Admin.NET.Core.Service;
using Admin.NET.Application.Const;
using Admin.NET.Application.Entity;
using Microsoft.AspNetCore.Http;
using Yitter.IdGenerator;
using Furion.DatabaseAccessor;
namespace Admin.NET.Application;
/// <summary>
/// 考试服务
/// </summary>
[ApiDescriptionSettings(ApplicationConst.GroupName, Order = 100)]
public class KaoshiService : IDynamicApiController, ITransient
{
    private readonly SqlSugarRepository<Kaoshi> _rep;
    private readonly SqlSugarRepository<KaoshiXueke> _kaoshiXuekeRep;
    private readonly SqlSugarRepository<Shichang> _shichangRep;
    private readonly SqlSugarRepository<Kaosheng> _kaoshengRep;
    private readonly SqlSugarRepository<Banji> _banjiRep;
    private readonly SqlSugarRepository<JiaoxueBan> _jiaoxueBanRep;
    public KaoshiService(SqlSugarRepository<Kaoshi> rep, SqlSugarRepository<KaoshiXueke> kaoshiXuekeRep, SqlSugarRepository<Shichang> shichangRep, SqlSugarRepository<Kaosheng> kaoshengRep, SqlSugarRepository<Banji> banjiRep, SqlSugarRepository<JiaoxueBan> jiaoxueBanRep)
    {
        _rep = rep;
        _kaoshiXuekeRep = kaoshiXuekeRep;
        _shichangRep = shichangRep;
        _kaoshengRep = kaoshengRep;
        _banjiRep = banjiRep;
        _jiaoxueBanRep = jiaoxueBanRep;
    }

    /// <summary>
    /// 分页查询考试
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Page")]
    public async Task<SqlSugarPagedList<KaoshiOutput>> Page(KaoshiInput input)
    {
        var query = _rep.AsQueryable()
            .WhereIF(!string.IsNullOrWhiteSpace(input.SearchKey), u =>
                u.Name.Contains(input.SearchKey.Trim())
                || u.PerNum.Contains(input.SearchKey.Trim())
                || u.Beizhu.Contains(input.SearchKey.Trim())
            )
            .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim()))
            .WhereIF(input.XuenianXueqiId>0, u => u.XuenianXueqiId == input.XuenianXueqiId)
            .WhereIF(!string.IsNullOrWhiteSpace(input.LeiBie), u => u.LeiBie == input.LeiBie)
            .WhereIF(!string.IsNullOrWhiteSpace(input.PerNum), u => u.PerNum.Contains(input.PerNum.Trim()))
            .WhereIF(!string.IsNullOrWhiteSpace(input.Status), u => u.Status == input.Status)
            .WhereIF(!string.IsNullOrWhiteSpace(input.Beizhu), u => u.Beizhu.Contains(input.Beizhu.Trim()))
            //处理外键和TreeSelector相关字段的连接
            .LeftJoin<XuenianXueqi>((u, xuenianxueqiid) => u.XuenianXueqiId == xuenianxueqiid.Id )
            .Select((u, xuenianxueqiid) => new KaoshiOutput
            {
                Id = u.Id,
                Name = u.Name,
                XuenianXueqiId = u.XuenianXueqiId, 
                XuenianXueqiIdFullname = xuenianxueqiid.Fullname,
                LeiBie = u.LeiBie,
                PerNum = u.PerNum,
                StartDate = u.StartDate,
                EndDate = u.EndDate,
                Status = u.Status,
                Beizhu = u.Beizhu,
                CreateUserName = u.CreateUserName,
                UpdateUserName = u.UpdateUserName,
            });
        if(input.StartDateRange != null && input.StartDateRange.Count >0)
        {
            DateTime? start= input.StartDateRange[0]; 
            query = query.WhereIF(start.HasValue, u => u.StartDate > start);
            if (input.StartDateRange.Count >1 && input.StartDateRange[1].HasValue)
            {
                var end = input.StartDateRange[1].Value.AddDays(1);
                query = query.Where(u => u.StartDate < end);
            }
        } 
        if(input.EndDateRange != null && input.EndDateRange.Count >0)
        {
            DateTime? start= input.EndDateRange[0]; 
            query = query.WhereIF(start.HasValue, u => u.EndDate > start);
            if (input.EndDateRange.Count >1 && input.EndDateRange[1].HasValue)
            {
                var end = input.EndDateRange[1].Value.AddDays(1);
                query = query.Where(u => u.EndDate < end);
            }
        } 
        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
    }

    /// <summary>
    /// 增加考试
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Add")]
    public async Task<long> Add(AddKaoshiInput input)
    {
        var entity = input.Adapt<Kaoshi>();
        await _rep.InsertAsync(entity);
        return entity.Id;
    }

    /// <summary>
    /// 删除考试
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Delete")]
    public async Task Delete(DeleteKaoshiInput input)
    {
        await _kaoshiXuekeRep.AsDeleteable().Where(p=>p.KaoshiId == input.Id).ExecuteCommandAsync();
        await _shichangRep.AsDeleteable().Where(p=>p.KaoshiId == input.Id).ExecuteCommandAsync();
        await _kaoshengRep.AsDeleteable().Where(p => p.KaoshiId == input.Id).ExecuteCommandAsync();
        var entity = await _rep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        //await _rep.FakeDeleteAsync(entity);   //假删除
        await _rep.DeleteAsync(entity);   //真删除
    }

    /// <summary>
    /// 更新考试
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "Update")]
    public async Task Update(UpdateKaoshiInput input)
    {
        var entity = input.Adapt<Kaoshi>();
        await _rep.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommandAsync();
    }

    /// <summary>
    /// 获取考试
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "Detail")]
    public async Task<Kaoshi> Detail([FromQuery] QueryByIdKaoshiInput input)
    {
        return await _rep.GetFirstAsync(u => u.Id == input.Id);
    }

    /// <summary>
    /// 获取考试列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpGet]
    [ApiDescriptionSettings(Name = "List")]
    public async Task<List<KaoshiOutput>> List([FromQuery] KaoshiInput input)
    {
        return await _rep.AsQueryable().Select<KaoshiOutput>().ToListAsync();
    }

    /// <summary>
    /// 班级考生座位表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "PrintBanji")]
    public async Task<List<PrintBanjiKaoshengDto>> PrintBanji(PrintBanjiKaoshiIdInput input)
    {
        var kaoshiId = input.KaoshiId;
        var kaoshi = await _rep.GetByIdAsync(kaoshiId);
        var banjiIds = await _kaoshengRep.AsQueryable().Where(p=>p.KaoshiId == kaoshiId).Distinct().Select(p=>p.BanjiId).ToListAsync();
        List<PrintBanjiKaoshengDto> list = new List<PrintBanjiKaoshengDto>();
        foreach (var banjiId in banjiIds)
        {
            var banji = await _banjiRep.GetByIdAsync(banjiId);
            PrintBanjiKaoshengDto dto = new PrintBanjiKaoshengDto();
            dto.KaoshiName = kaoshi.Name;
            dto.BanjiName = banji.Name;
            dto.PrintDate = DateTime.Now;
            dto.items = await _kaoshengRep.AsQueryable()
                .LeftJoin<Kaoshi>((u, kaoshiid) => u.KaoshiId == kaoshiid.Id)
                .LeftJoin<Banji>((u, kaoshiid, banjiid) => u.BanjiId == banjiid.Id)
                .LeftJoin<Student>((u, kaoshiid, banjiid, studentid) => u.StudentId == studentid.Id)
                .Where(u=>u.KaoshiId == kaoshiId && u.BanjiId == banjiId)
                .Select((u, kaoshiid, banjiid, studentid) => new PrintBanjiKaoshengItemDto
                {
                    Xh=studentid.Xh,
                    Name=studentid.Name,
                    ZhunkaoZhenghao = u.ZhunkaoZhenghao,
                    ShiChangNum = u.ShiChangNum,
                    ZuoweiHao = u.ZuoweiHao
                }).ToListAsync();
            list.Add(dto);
        }
        return list;
    }

    /// <summary>
    /// 教学班考生座位表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "PrintJiaoxueBan")]
    public async Task<List<PrintBanjiKaoshengDto>> PrintJiaoxueBan(PrintBanjiKaoshiIdInput input)
    {
        var kaoshiId = input.KaoshiId;
        var kaoshi = await _rep.GetByIdAsync(kaoshiId);
        var banjiIds = await _kaoshengRep.AsQueryable().Where(p => p.KaoshiId == kaoshiId).Distinct().Select(p => p.JiaoxueBanId).ToListAsync();
        List<PrintBanjiKaoshengDto> list = new List<PrintBanjiKaoshengDto>();
        foreach (var banjiId in banjiIds)
        {
            var banji = await _jiaoxueBanRep.GetByIdAsync(banjiId);
            PrintBanjiKaoshengDto dto = new PrintBanjiKaoshengDto();
            dto.KaoshiName = kaoshi.Name;
            dto.BanjiName = banji.Name;
            dto.PrintDate = DateTime.Now;
            dto.items = await _kaoshengRep.AsQueryable()
                .LeftJoin<Kaoshi>((u, kaoshiid) => u.KaoshiId == kaoshiid.Id)
                .LeftJoin<JiaoxueBan>((u, kaoshiid, jiaoxueBanid) => u.JiaoxueBanId == jiaoxueBanid.Id)
                .LeftJoin<Student>((u, kaoshiid, jiaoxueBanid, studentid) => u.StudentId == studentid.Id)
                .Where(u => u.KaoshiId == kaoshiId && u.JiaoxueBanId == banjiId)
                .Select((u, kaoshiid, jiaoxueBanid, studentid) => new PrintBanjiKaoshengItemDto
                {
                    Xh = studentid.Xh,
                    Name = studentid.Name,
                    ZhunkaoZhenghao = u.ZhunkaoZhenghao,
                    ShiChangNum = u.ShiChangNum,
                    ZuoweiHao = u.ZuoweiHao
                }).ToListAsync();
            foreach (var item in dto.items)
            {
                var shichang = await _shichangRep.AsQueryable().Where(p => p.KaoshiId == kaoshi.Id && p.ShiChangNum == item.ShiChangNum).FirstAsync();
                if(shichang != null)
                    item.Address1 = shichang.Address1;
            }
            list.Add(dto);
        }
        return list;
    }
    
    /// <summary>
    /// 考场验收单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [ApiDescriptionSettings(Name = "PrintShichang")]
    public async Task<List<PrintBanjiKaoshengDto>> PrintShichang(PrintBanjiKaoshiIdInput input)
    {
        var kaoshiId = input.KaoshiId;
        var kaoshi = await _rep.GetByIdAsync(kaoshiId);
        var shichagns = await _shichangRep.AsQueryable().Where(p => p.KaoshiId == kaoshiId).ToListAsync();
        List<PrintBanjiKaoshengDto> list = new List<PrintBanjiKaoshengDto>();
        foreach (var shichang in shichagns)
        {
            PrintBanjiKaoshengDto dto = new PrintBanjiKaoshengDto();
            dto.KaoshiName = kaoshi.Name;
            dto.ShiChangNum = shichang.ShiChangNum;
            dto.Address1 = shichang.Address1;
            dto.PrintDate = DateTime.Now;
            dto.items = await _kaoshengRep.AsQueryable()
                .LeftJoin<Kaoshi>((u, kaoshiid) => u.KaoshiId == kaoshiid.Id)
                .LeftJoin<Banji>((u, kaoshiid, banjiid) => u.BanjiId == banjiid.Id)
                .LeftJoin<Student>((u, kaoshiid, banjiid, studentid) => u.StudentId == studentid.Id)
                .Where(u => u.KaoshiId == kaoshiId && u.ShiChangNum == shichang.ShiChangNum)
                .OrderBy(u=>u.ZuoweiHao)
                .Select((u, kaoshiid, banjiid, studentid) => new PrintBanjiKaoshengItemDto
                {
                    Xh = studentid.Xh,
                    Name = studentid.Name,
                    ZhunkaoZhenghao = u.ZhunkaoZhenghao,
                    ShiChangNum = u.ShiChangNum,
                    ZuoweiHao = u.ZuoweiHao
                }).ToListAsync();
            list.Add(dto);
        }
        return list;
    }

    /// <summary>
    /// 获取学年学期列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "XuenianXueqiXuenianXueqiIdDropdown"), HttpGet]
    public async Task<dynamic> XuenianXueqiXuenianXueqiIdDropdown()
    {
        return await _rep.Context.Queryable<XuenianXueqi>()
                .Select(u => new
                {
                    Label = u.Fullname,
                    Value = u.Id
                }
                ).ToListAsync();
    }

    /// <summary>
    /// 复制考试
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost]
    [UnitOfWork]
    [ApiDescriptionSettings(Name = "Copy")]
    public async Task Copy(CopyKaoshiIdInput input)
    {
        var xuekes = await _kaoshiXuekeRep.AsQueryable().Where(p => p.KaoshiId == input.Id).ToListAsync();
        var shichangs = await _shichangRep.AsQueryable().Where(p => p.KaoshiId == input.Id).ToListAsync();
        var kaoshengs = await _kaoshengRep.AsQueryable().Where(p => p.KaoshiId == input.Id).ToListAsync();
        var kaoshi = await _rep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
        kaoshi.Id = YitIdHelper.NextId();
        kaoshi.Name += "copy";
        await _rep.InsertAsync(kaoshi);
        foreach (var x in xuekes)
        {
            x.Id = YitIdHelper.NextId();
            x.KaoshiId = kaoshi.Id;
            await _kaoshiXuekeRep.InsertAsync(x);
        }
        foreach (var x in shichangs)
        {
            x.Id = YitIdHelper.NextId();
            x.KaoshiId = kaoshi.Id;
            await _shichangRep.InsertAsync(x);
        }
        foreach(var x in kaoshengs)
        {
            x.Id = YitIdHelper.NextId();
            x.KaoshiId = kaoshi.Id;
            await _kaoshengRep.InsertAsync(x);
        }
    }



}

